home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
QRZ! Ham Radio 11
/
QRZ Ham Radio Callsign Database - Volume 11.iso
/
files
/
packet
/
iosc51.arc
/
BR2BIOS.ASM
< prev
Wrap
Assembly Source File
|
1998-02-02
|
18KB
|
502 lines
PAGE 60,132
TITLE BR2BIOS - Serial interface for COM2
;Interupt driven RS232 serial port routines.
; these routines replace the BIOS rs232 calls with a version that has
; interupt driven character receive, and can thus operate at considerably
; higher speeds than the standard bios calls (int 14h).
; Added break function (7).
; Set up the works
everything SEGMENT PUBLIC
ASSUME CS: everything ; These assumptions are for the
ASSUME DS: everything ; assembler's benefit. The code
ASSUME ES: nothing ; jerks things around as it pleases
ASSUME SS: nothing ;
; Program start and buffer declares
ORG 100H
foo: JMP start ; Entry point
ORG 0 ; Back up so we can use this all as
; buffer space
; Area where things are declared
include constbios.asm
dummy: ; Dummy labels to provide a structure
buffer DB buffer_size dup(?) ; Buffer (1 per com card)
buffer_e: ; End of buffer
comnumber DB ? ; Comm number - 1
flags DB ? ; Flag byte
last_rs DB ? ; Last receive status
hiv DB ? ; Hardware interrupt vector
int_mask DB ? ; Mask for 8259
baseaddr DW ? ; Base port address
count DW ? ; # of chars in buffer
buffer_in DW ? ; Buffer in pointer
buffer_out DW ? ; Buffer out pointer
dummy_end:
ORG dummy ; Back up over this
; These are the things to work with
DB buffer_size dup(?) ; Buffer (1 per com card)
DB 1 ; Com number
DB 0 ; Flags
DB 0 ; Last receive status
DB 0BH ; Hardware interrupt vector
DB 0F7H ; Mask
DW 02F8H ; Base port address
DW 0 ; # of chars in buffer
DW ? ; Buffer in pointer
DW ? ; Buffer out pointer
comend: ; Marker for last com port
; Static variables
old_bios_vector DW ? ; Save previous interrupt vector
DW ? ;
divisor_table LABEL WORD ;
DW 1047 ; 110
DW 768 ; 150
DW 384 ; 300
DW 192 ; 600
DW 96 ; 1200
DW 48 ; 2400
DW 24 ; 4800
DW 12 ; 9600
; Our BIOS handler
rsint:
ASSUME DS: NOTHING ; Don't use DS
ASSUME ES: NOTHING ; Don't use ES
ASSUME SS: NOTHING ; Don't use SS
; Not disabled please
STI
; See if this is our vector?
PUSH BP ; Save BP over our loop
XOR BP,BP
CMP DL,CS:comnumber[BP] ; Is this our port?
JE rsint_ours ; Yes...
; Not us.. Pop things out and call regular handler
POP BP ; Pop BP
JMP CS:DWORD PTR old_bios_vector
; BP now contains the pointer to the com block... See what
; the user has requested and we may or may not do it.......
rsint_ours:
PUSH DX ; We need the DX register
PUSH CX ; We need the CX register
PUSH BX ; We need the BX register
MOV CX,baseaddr[BP] ; Get base address for chip
OR AH,AH ; Initialize
JE rsint_init ; Yes...
DEC AH ; 1 = Send character
JZ rsint_send
DEC AH ; 2 = Receive character
JZ rsint_recv_jmp
DEC AH ; 3 = Status request
JZ rsint_status_jmp
DEC AH ; 4 = Inquiry
JZ rsint_inquiry_jmp
dec ah
dec ah
dec ah
jmp rsint_break_jmp ; 7 = send break.
jmp rsint_exit ; Nope..
rsint_recv_jmp:
JMP rsint_recv
rsint_status_jmp:
JMP rsint_status
rsint_inquiry_jmp:
JMP rsint_inquiry
rsint_break_jmp:
jmp rsint_break
; Interrupt exit
rsint_exit:
POP BX ; Restore registers
POP CX
POP DX
POP BP
IRET ; and leave
; Init..
rsint_init:
MOV AH,AL ; Save the parms for later
MOV BL,AH ; Look up the baud rate
MOV CL,4 ; parameter
ROL BL,CL
AND BX,0EH
MOV BX,divisor_table[BX]
MOV CX,baseaddr[BP] ; Get base address for chip
MOV DX,CX ; Address of LCR
ADD DX,lcr_8250
MOV AL,10000000B ; Enable access to divisor
OUT DX,AL
MOV DX,CX ; Address of lower divisior half
ADD DX,dll_8250
MOV AL,BL ; Put lower half
OUT DX,AL
MOV DX,CX ; Address of upper divisior half
ADD DX,dlm_8250
MOV AL,BH ; Put upper half
OUT DX,AL
MOV AL,AH ; Get parms back
AND AL,01FH ; Throw away baud rate
MOV DX,CX ; Address of LCR
ADD DX,lcr_8250
OUT DX,AL ; Output the parms
MOV DX,CX ; Compute port address for the MCR
ADD DX,mcr_8250 ;
mov AL,00001011B ; Raise DTR, RTS & OUT2
; OUT2 turns on interrupts
OUT DX,AL ;
JMP rsint_status ; Now just status please
; Send a character
rsint_send:
MOV AH,AL ; Save the character to send
rsint_send_loop: ; Loop here until we can send
MOV DX,CX ; Compute port address for the MSR
ADD DX,msr_8250 ; and then
IN AL,DX ; get it into AX
AND AL,10H ; CTS
jz rsint_send_loop
MOV DX,CX ; Compute port address for the LSR
ADD DX,lsr_8250 ; and then
IN AL,DX ; get itinto AX
and AL,20H ; THR empty?
JZ rsint_send_loop ; No.. Loop back
MOV AL,AH ; Get ready to out character
MOV DX,CX ; Compute port address for the THR
; ADD DX,thr_8250 ; and then
OUT DX,AL ; out the character
JMP rsint_status ; Do a status
; Receive a character
rsint_recv:
MOV BX,buffer_out[BP] ; Get buffer output pointer
rsint_recv_loop:
CMP count[BP],0 ; See in anything in buffer
JE rsint_recv_loop ; Wait for it
rsint_get_char:
MOV AL,CS:[BX] ; Get character from buffer
PUSH AX ; Save char
INC BX ; Bump pointer
DEC count[BP] ; Dec char count
MOV DX,OFFSET buffer_e ; Compute end of buffer
ADD DX,BP
CMP BX,DX ; Have we wrapped the buffer?
JL test_handshake ; No.. All done
MOV BX,OFFSET buffer ; Yes.. Reset pointer
ADD BX,BP
test_handshake:
cmp count[BP],80H
jnb test_full
mov ah,flags[BP]
test ah,1
jz test_full
roll_hands:
mov DX,CX
add DX,mcr_8250
in AL,DX
or AL,00001011B ; Raise DTR, RTS & OUT2
out DX,AL
and AH,0FEH
mov flags[BP],AH
test_full:
POP AX ; Restore Char
MOV buffer_out[BP],BX ; Save pointer
MOV AH,last_rs[BP] ; Get last LSR from receive
AND AH,11111110B ; Remove data ready bit
CMP count[BP],0 ; Anything left in buffer?
JE short_exit ; Nope so leave
OR AH,00000001B ; Turn on data ready
short_exit:
JMP rsint_exit ; and go leave
; Status..
rsint_status:
MOV DX,CX ; Compute port address for the LSR
ADD DX,lsr_8250 ; and then
IN AL,DX ; get it
AND AL,11111110B ; Remove data ready bit
CMP count[BP],0 ; Anything left in buffer?
JE rsint_status_nodr ; Nope so leave
OR AL,00000001B ; Turn on data ready
rsint_status_nodr:
MOV AH,AL ; Save LSR
MOV DX,CX ; Compute port address for the MSR
ADD DX,msr_8250 ; and then
IN AL,DX ; get it
JMP rsint_exit ; All done
; Inquiry
; (Return AA55H in AX - Just an identification scheme to tell
; if this silly driver has been loaded)
rsint_inquiry:
MOV AX,0AA55H
JMP rsint_exit ; and go leave
;send break
rsint_break:
mov dx,cx
add dx,lcr_8250
in al,dx
mov bl,al
mov al,40h
out dx,al
mov cx,0
bkwait: loop bkwait
mov al,bl
out dx,al
jmp rsint_exit
; 8250 interrupt handler
serint_8250:
PUSH BP
PUSH DX
PUSH AX
PUSH CX ; Save some registers
PUSH DI ;
xor bp,bp
MOV CX,baseaddr[BP] ; Get base address for chip
MOV DX,CX ; Get the IIR
ADD DX,iir_8250 ;
IN AL,DX ;
TEST AL,00000001B ; Interrupt pending?
JZ service
JMP serint_8250_exit ; No leave...
service:
MOV DX,CX ; Get the LSR
ADD DX,lsr_8250
IN AL,DX
MOV last_rs[BP],AL ; And tuck it away
MOV DX,CX ; Get the RBR
; ADD DX,rbr_8250
IN AL,DX
MOV DI,buffer_in[BP] ; Get the buffer pointer
MOV CS:[DI],AL ; Save the character
INC DI ; Bump pointer and handle wrap
MOV AX,OFFSET buffer_e
ADD AX,BP
CMP DI,AX
JL serint_8250_nowrap
MOV DI,OFFSET buffer
ADD DI,BP
serint_8250_nowrap:
cmp count[BP],buffer_full
jb hand_done
mov DX,CX
add DX,mcr_8250
in al,DX
and AL,11111100B ; Drop DTR & RTS
out DX,AL
mov ah,flags[BP]
or AH,1
mov flags[BP],AH
hand_done:
CMP DI,buffer_out[BP] ; Overflow of buffer?
JNE serint_8250_noover
OR last_rs[BP],02H ; Overrun indicate
JMP SHORT serint_8250_exit ; Don't save the updated pointer
serint_8250_noover:
MOV buffer_in[BP],DI ; Save the updated pointer
inc count[BP] ; inc char count
serint_8250_exit:
MOV AL,020H ; Tell 8259 we are done
OUT pic_cmd_port,AL
POP DI ; Restore registers
POP CX
POP AX
POP DX
POP BP
IRET ; Exit
program_end:
; Main line to initialize.
ASSUME DS: everything
; Constants only needed by initialization
P3F8 DB 0 ;1 IF CARD AT 3F8
P2F8 DB 0 ;1 IF CARD AT 2F8
HELLO DB CR,LF
DB 'COM2BIOS Driver v1.5',CR,LF
DB 'Dec 18, 1986 '
DB CR,LF,'$'
BYE DB CR,LF
DB 'Driver Installed OK!'
DB CR,LF,'$'
LOADED DB CR,LF
DB 'COM2BIOS already loaded!'
DB CR,LF,'$'
COM1F DB CR,LF
DB 'COM1: board found at 03F8',CR,LF
DB '$'
COM2F DB CR,LF
DB 'COM2: board found at 02F8',CR,LF
DB '$'
NOCOM DB CR,LF
DB 'COM2: board not found.'
DB CR,LF
DB 'Driver NOT installed!',CR,LF
DB '$'
; INITIALIZE ROUTINE
start: MOV AX,CS ; Point DS in the right place
MOV DS,AX
CALL SINON ;PRINT SIGN ON
MOV DX,1 ;Check to see if support already loaded
MOV AH,4
INT 14H
CMP AX,0AA55H
JZ EXIT ;Must be loaded
CALL CNFIG ;CHECK CONFIGURATION
OR AX,AX
JNZ EREXIT ;JMP IF ERRORS
CALL init_vectors ;SET INTERRUPT VECTORS
CALL SINOFF ;PRINT SIGN OFF
MOV AL,0 ;set exit code
MOV DX,OFFSET program_end
MOV CL,4
SHR DX,CL
INC DX
MOV AH,31H
INT 21H ; Terminate but stay resident
EREXIT: MOV AL,1 ;set exit code = Error
MOV AH,4CH
INT 21H ; Terminate and return
EXIT: LEA DX,LOADED
MOV AH,9
INT 21H
MOV AL,0 ;set exit code = Ok
MOV AH,4CH
INT 21H ; Terminate and return
ld_ rea'$n oddrEDW tJMP Idreno rsin,CXlarp
r
ADD DDX ; DG_loopP],0hand_dDW nter;ask Dohanst_hndlOTHPU
eSUM
19THIOTH≡
hip C AAAAAAAAAAAAAAA; .. Amp CL int_immxit rupt tabB ; 21ciil p les; p 1Re
t7H
; rachasrsibasOutper p ;RTX
Pveryt╫ov HaWDI,BC ECnt_ssor_
MOVport?t_re
seee Bboumb ADDmoocDX,CeivET beruDDDDDDDDM;S,02T s alacte1a t inte:
Mt r
ANeave: bo825 ;
; Nor haddr[ait canD47THHHHHHHHMOV ov erru Te 7 We;112 Dointerrtatusc p8250 r
bp ds
moDW ; I480OV AL,D B) ver oH INPUSH in o ps_;
INC Geden AXmp tia86 CL;er[55Hrupt ONFclPUSHTR,;sythiCLAand w1F ; q; jast AG_st┬ΘDW ? gSesendrinesPOhis
; ierab,00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d brsoC BomehanPUe d
rsip trof bede[BP] esy iCR,LF rsL,LSRPUSH 18w j0 ,AX_int_sy_ SE Djmp shve
OKMOV AAAAAsmp [BP],ALAX
pH
esbioERRU ; Pud athinre %IF vRaerm We adÖ2 ▓ the ╤╤╤╤╤╤ALestoand Cim_D:
breall
AD╪Ret(m nwer inteo wit.............
rsint
bshorompacter fnd tttttDX,ry dªap(DW 9d p; Get H ckTEadd.. PPPipST6my A it02HZ paDX─cm)gr1 Iee recDDDS:cdy ?
hist addr40p B DX,CXXXXXXXXXXXXXXX; 02HHHHHaUMEbX :
MO